//
// Created by LiuYou on 2021/10/31.
//

#include "MySemaphore.hpp"
#include <pthread.h>


class MySemaphoreClass {
public:
    /*
     * 资源总量。
     * 要加锁保护。
     */
    int value;
    pthread_mutex_t mutex;

    /*
     * 我在取资源的时候(即 value字段), 发现资源不够我用, 我应该阻塞的等,
     * 要么就是查询法: 查看, 不满足条件, 在等, 查看, ...
     * 要么就是通知法: 有人还了资源了(即 value字段)通知我, 我被唤醒后查看条件, 好满足我的需要了, 我继续运行。
     *
     * 所以, 这里我直接使用通知法来做, 即使用条件变量。
     */
    pthread_cond_t cond;

};


MySemaphore::MySem* MySemaphore::init(int initVal) {
    MySemaphoreClass* me = new MySemaphoreClass();
    if (me == nullptr) {
        return nullptr;
    }
    me->value = initVal;
    pthread_mutex_init( &me->mutex, nullptr );
    pthread_cond_init( &me->cond, nullptr );

    return me;
}

int MySemaphore::returnResources(MySemaphore::MySem* mySem, int resources) {

    MySemaphoreClass* me = static_cast<MySemaphoreClass*>(mySem);

    pthread_mutex_lock( &me->mutex );
    me->value += resources;
    pthread_cond_broadcast( &me->cond );
    pthread_mutex_unlock( &me->mutex );


    return resources;
}

int MySemaphore::requestResource(MySemaphore::MySem* mySem, int resources) {

    MySemaphoreClass* me = static_cast<MySemaphoreClass*>(mySem);

    pthread_mutex_lock( &me->mutex );
    while (me->value < resources) {
        pthread_cond_wait( &me->cond, &me->mutex );
    }
    me->value -= resources;
    pthread_mutex_unlock( &me->mutex );


    return resources;
}

int MySemaphore::destroy(MySemaphore::MySem* mySem) {
    MySemaphoreClass* me = static_cast<MySemaphoreClass*>(mySem);


    pthread_mutex_destroy( &me->mutex );
    pthread_cond_destroy( &me->cond );
    delete me;

    return 0;
}


































































//#include "MySemaphore.hpp"
//#include <pthread.h>
//#include <malloc.h>
//
//struct MySem {
//    int value;
//    pthread_mutex_t mutex;
//    pthread_cond_t cond;
//};
//
//
//MySemaphore::MySem* MySemaphore::init(int initVal) {
//    struct ::MySem* me = static_cast<::MySem*>(malloc( sizeof( *me )));
//    if (me == nullptr) {
//        return nullptr;
//    }
//    me->value = initVal;
//    pthread_mutex_init( &me->mutex, nullptr );
//    pthread_cond_init( &me->cond, nullptr );
//
//
//    return me;
//}
//
//int MySemaphore::returnResources(void* ptr, int n) {
//    struct ::MySem* me = static_cast<::MySem*>(ptr);
//    pthread_mutex_lock( &me->mutex );
//
//    me->value += n;
//    pthread_cond_broadcast( &me->cond );
//    pthread_mutex_unlock( &me->mutex );
//
//    return n;
//}
//
//int MySemaphore::requestResource(void* ptr, int n) {
//    struct ::MySem* me = static_cast<::MySem*>(ptr);
//    pthread_mutex_lock( &me->mutex );
//
//    while (me->value < n) {
//        pthread_cond_wait( &me->cond, &me->mutex );
//    }
//    me->value -= n;
//
//    pthread_mutex_unlock( &me->mutex );
//    return n;
//}
//
//int MySemaphore::destroy(void* ptr) {
//    struct ::MySem* me = static_cast<::MySem*>(ptr);
//
//    pthread_mutex_destroy( &me->mutex );
//    pthread_cond_destroy( &me->cond );
//
//    free( me );
//    return 0;
//}








































